<template>
  <div id="home">
    <el-row type="flex" justify="center">
      <el-col :xl="18" :lg="12" :md="14" :sm="16" :xs="20">
        <h1>三合一收款码</h1>
        <el-divider></el-divider>
      </el-col>
    </el-row>

    <!-- 二维码上传面板 -->
    <el-row type="flex" justify="center" class="qrbox">
      <el-col :xl="10" :lg="12" :md="14" :sm="16" :xs="20">
        <el-row type="flex" justify="space-around" class="qrmobile">
          <!-- 微信 -->
          <el-col :xl="6" :lg="8" :md="12" :sm="16" :xs="12">
            <el-tag type="success">微信收款码二维码</el-tag>
            <el-upload
              class="avatar-uploader wx"
              action="string"
              :data="{type:'wx'}"
              :show-file-list="false"
              :http-request="upload"
              :on-success="uploadSuccess"
              :on-error="uploadError"
              accept="image/gif, image/jpeg, image/png"
              ref="wx"
            >
              <img v-if="Img.wxImg" :src="Img.wxImg" class="avatar" />
              <i v-else class="el-icon-plus avatar-uploader-icon"></i>
            </el-upload>
          </el-col>

          <!-- 支付宝 -->
          <el-col :xl="6" :lg="8" :md="12" :sm="16" :xs="12">
            <el-tag>支付宝收款码二维码</el-tag>
            <el-upload
              class="avatar-uploader zfb"
              action="string"
              :data="{type:'zfb'}"
              :show-file-list="false"
              :http-request="upload"
              :on-success="uploadSuccess"
              :on-error="uploadError"
              accept="image/gif, image/jpeg, image/png"
              ref="zfb"
            >
              <img v-if="Img.zfbImg" :src="Img.zfbImg" class="avatar" />
              <i v-else class="el-icon-plus avatar-uploader-icon"></i>
            </el-upload>
          </el-col>

          <!-- QQ -->
          <el-col :xl="6" :lg="8" :md="12" :sm="16" :xs="12">
            <el-tag type="info">QQ收款码二维码</el-tag>
            <el-upload
              class="avatar-uploader qq"
              action="string"
              :data="{type:'qq'}"
              :show-file-list="false"
              :http-request="upload"
              :on-success="uploadSuccess"
              :on-error="uploadError"
              accept="image/gif, image/jpeg, image/png"
              ref="qq"
            >
              <img v-if="Img.qqImg" :src="Img.qqImg" class="avatar" />
              <i v-else class="el-icon-plus avatar-uploader-icon"></i>
            </el-upload>
          </el-col>
        </el-row>
      </el-col>
    </el-row>

    <!-- 提示文字 -->
    <el-row type="flex" justify="center">
      <el-col :xl="6" :lg="8" :md="10" :sm="14" :xs="20">
        <el-alert
          type="warning"
          :closable="false"
          center
          show-icon
          title="只能上传png、jpg、gif文件，且不超过 2MB!"
        ></el-alert>
      </el-col>
    </el-row>

    <!-- 收款人姓名 -->
    <el-row type="flex" justify="center" class="form">
      <el-col :xl="18" :lg="12" :md="14" :sm="16" :xs="20">
        <el-input
          type="text"
          placeholder="请输入收款人姓名"
          maxlength="11"
          v-model="userInfo.payee"
          clearable
        ></el-input>
      </el-col>
    </el-row>
    <!-- 收款人QQ -->
    <el-row type="flex" justify="center" class="form">
      <el-col :xl="18" :lg="12" :md="14" :sm="16" :xs="20">
        <el-input type="text" placeholder="请输入QQ号" maxlength="11" v-model="userInfo.qq" clearable></el-input>
      </el-col>
    </el-row>
    <!-- 轮播展示二维码背景 -->
    <el-row type="flex" justify="center">
      <el-col :xl="18" :lg="16" :md="16" :sm="16" :xs="20">
        <swiper :options="swiperOption" ref="mySwiper">
          <swiperSlide v-for="(v, index) in qrbg" :key="index">
            <div class="qrimg" :style="{'background-image':'url(imgs/bgimgs/'+v+'.png)'}"></div>
          </swiperSlide>
          <div class="swiper-pagination" slot="pagination"></div>
        </swiper>
      </el-col>
    </el-row>
    <!-- 生成二维码 -->
    <el-row type="flex" justify="center">
      <el-button
        type="primary"
        :xl="18"
        :lg="12"
        :md="14"
        :sm="16"
        :xs="20"
        class="btn"
        @click="sub"
        v-loading.fullscreen.lock="fullscreenLoading"
      >生成二维码</el-button>
    </el-row>

    <!-- 用于测试 -->
    <!-- <el-button
      type="primary"
      :xl="18"
      :lg="12"
      :md="14"
      :sm="16"
      :xs="20"
      class="btn"
      @click="cs"
    >cs</el-button>-->
    <!-- 右侧抽屉，二维码生成展示面板 -->
    <el-drawer
      title="二维码生成成功！请点击二维码进行保存！"
      :visible.sync="qrdrawer"
      :before-close="handleClose"
      :wrapperClosable="false"
    >
      <img :src="cvsImg" id="cvsImg" @click="download" />
    </el-drawer>
  </div>
</template>

<script>
import { Vue, Component } from "vue-property-decorator";
import swiper from "../components/Swiper";
import swiperSlide from "../components/SwiperSlide.vue";
import jsQR from "jsqr";
import CryptoJS from "crypto-js";
import QRCode from "qrcode";
import ArtQRCode from "../assets/artqrcode";
import { urlEncode, Encrypt } from "../assets/utils";

@Component({
  components: { swiper, swiperSlide }
})
export default class Home extends Vue {
  qrdrawer = false; //抽屉开关
  fullscreenLoading = false; //loading开关
  loadText = "正在生成二维码，请稍后..."; //loading提示文字
  Img = {
    //上传图片的信息
    wxImg: "",
    zfbImg: "",
    qqImg: ""
  };
  /********** 用户信息，加密生成二维码 *************/
  userInfo = {
    wxCode: "",
    zfbCode: "",
    qqCode: "",
    qq: "",
    payee: ""
  };

  cvs = null; //创建的一个canvas
  cvsImg = null; //canvas生成图片的url

  qrconfig = {}; //二维码背景的配置信息
  qrbg = []; //二维码背景的名字
  /************ 轮播图的配置 ************/
  swiperOption = {
    mousewheel: true,
    effect: "coverflow",
    grabCursor: true,
    centeredSlides: true,
    slidesPerView: "auto",
    coverflowEffect: {
      rotate: 50,
      stretch: 0,
      depth: 100,
      modifier: 1,
      slideShadows: true
    },
    pagination: {
      el: ".swiper-pagination",
      clickable: true
    }
  };

  /**
   * 创建轮播图，加载二维码背景图片配置
   *
   *
   */

  created() {
    this.cvs = document.createElement("canvas");
    this.getQrcodeCfg().then(res => {
      this.qrconfig = res;
      this.qrbg = Object.keys(this.qrconfig.putong);
    });
  }
  mounted() {}
  /**
   * 测试用代码
   */
  cs() {
    this.$nextTick(() => {
      this.fullscreenLoading = true;
      const activeIndex = this.$refs.mySwiper.swiper.activeIndex;
      const isArt = this.qrconfig.putong[this.qrbg[activeIndex]].art;
      if (isArt) {
        this.makeArtQrcode(this.qrbg[activeIndex], "csart");
      } else {
        this.makeCommonQrcode(this.qrbg[activeIndex], "cs");
      }
    });
  }

  /**
   * 下载生成二维码
   */
  download() {
    const a = document.createElement("a");
    a.href = this.cvsImg;
    a.download = `万能收款码${
      this.userInfo.payee ? "--" + this.userInfo.payee : ""
    }.png`;
    a.click();
  }
  /**
   * 关闭抽屉询问，清除画布
   */
  handleClose(done) {
    this.$confirm("确认关闭？")
      .then(res => {
        const cxt = this.cvs.getContext("2d");
        cxt.clearRect(0, 0, this.cvs.width, this.cvs.height);
        done();
      })
      .catch(err => {});
  }
  /**
   * 上传二维码进行解析，正则验证是否为正确的二维码，采用element-ui的upload组件
   */
  upload(params) {
    const file = params.file,
      fileType = file.type,
      isImage = fileType.indexOf("image") != -1,
      isLt2M = file.size / 1024 / 1024 < 2;
    // 这里常规检验，看项目需求而定
    if (!isImage) {
      this.$message.error("只能上传图片格式png、jpg、gif!");
      return;
    }
    if (!isLt2M) {
      this.$message.error("只能上传图片大小小于2M");
      return;
    }
    this.fileDecode(params.file).then(res => {
      const ImgCode = res.data;
      switch (params.data.type) {
        case "wx":
          if (ImgCode.indexOf("wxp") == "-1") {
            params.onError({ type: "wx", msg: "微信" });
          } else {
            this.userInfo.wxCode = ImgCode;
            params.onSuccess(params.data.type);
          }
          break;
        case "zfb":
          if (
            ImgCode.indexOf("ALIPAY") == "-1" &&
            ImgCode.indexOf("alipay") == "-1"
          ) {
            params.onError({ type: "zfb", msg: "支付宝" });
          } else {
            this.userInfo.zfbCode = ImgCode;
            params.onSuccess(params.data.type);
          }
          break;
        case "qq":
          if (ImgCode.indexOf("qianbao") == "-1") {
            params.onError({ type: "qq", msg: "QQ" });
          } else {
            this.userInfo.qqCode = ImgCode;
            params.onSuccess(params.data.type);
          }
          break;
      }
    });
  }
  /**
   * 上传成功回调，展示二维码
   * @param res 参数：wx，zfb,qq
   * @param file 文件信息
   */
  uploadSuccess(res, file) {
    this.Img[res + "Img"] = URL.createObjectURL(file.raw);
  }
  /**
   * 上传失败回调，弹出错误信息
   * @param res 需要显示的信息
   */
  uploadError(res) {
    this.$message.error(
      `错了哦!该收款码不是${res.msg}收款码，请上传${res.msg}收款码!`
    );
  }
  /**
   * 生成二维码，并验证信息是否正确
   */
  sub() {
    if (this.qq) {
      if (!/^[0-9]{5,10}$/.test(this.qq)) {
        this.$message.error(`请输入正确的QQ号码!`);
        return;
      }
    }
    if (!this.userInfo.wxCode) {
      this.$message.error(`请上传微信收款码!`);
      return;
    }
    if (!this.userInfo.zfbCode) {
      this.$message.error(`请上传支付宝收款码!`);
      return;
    }
    if (!this.userInfo.qqCode) {
      this.$message.error(`请上传QQ收款码!`);
      return;
    }
    if (/\d{5,11}/.test(this.qq)) {
      this.$message.error(`请输入正确的QQ号码!`);
      return;
    }

    //加密信息，在url中用?mm=进行传参
    const mm = Encrypt(JSON.stringify(this.userInfo));
    const longUrl = `${document.location.protocol}//${window.location.host}${
      window.location.pathname
    }allqr?mm=${urlEncode(mm)}`;

    this.fullscreenLoading = true;
    //生成短链，从env中获取短链api
    this.axios.get('long2dwz?dwzapi=urlcn&url='+longUrl).then(res => {
      //获取选择的二维码背景
      const activeIndex = this.$refs.mySwiper.swiper.activeIndex;
      const isArt = this.qrconfig.putong[this.qrbg[activeIndex]].art;
      // 判断是否为艺术二维码
      if (isArt) {
        this.makeArtQrcode(this.qrbg[activeIndex], res.data.ae_url);
      } else {
        this.makeCommonQrcode(this.qrbg[activeIndex], res.data.ae_url);
      }
    });
  }
  /**
   * 普通二维码配置参数
   * @param qrbgName 二维码背景名字
   * @param tinyUrl 短连接url
   */
  makeCommonQrcode(qrbgName, tinyUrl) {
    const params = {
      qrbgName: qrbgName,
      imgUrl: `imgs/bgimgs/${qrbgName}.png`, //二维码背景图片地址
      qrconfig: this.qrconfig.putong[qrbgName], //二维码配置
      tinyUrl: tinyUrl
    };
    this.makeDiyBg(params);
  }
  /**
   * 生成艺术二维码
   * @param mouldName 二维码背景名字
   * @param tinyUrl 短连接url
   */
  makeArtQrcode(mouldName, tinyUrl) {
    this.qrconfig.yishu[
      mouldName
    ].materials.border = `imgs/bgimgs/${mouldName}.png`; //艺术二维码背景名字
    //艺术二维码配置
    const artOptions = {
      text: tinyUrl,
      width: this.qrconfig.yishu[mouldName].imgWidth,
      height: this.qrconfig.yishu[mouldName].imgHeight,
      codeWidth: this.qrconfig.yishu[mouldName].qrWidth,
      codeHeight: this.qrconfig.yishu[mouldName].qrHeight,
      top: this.qrconfig.yishu[mouldName].qrTop,
      left: this.qrconfig.yishu[mouldName].qrLeft,
      materials: JSON.parse(
        //深拷贝的原始数据对象，防止添加vue属性
        JSON.stringify(this.qrconfig.yishu[mouldName].materials)
      )
    };
    this.qrdrawer = true;
    this.fullscreenLoading = false;
    this.$nextTick(() => {
      try {
        /**************  生成艺术二维码，artCvs返回一个canvas ***********/
        const artCvs = new ArtQRCode(this.cvs, artOptions, status => {
          if (status == "success") {
            const ctx = this.cvs.getContext("2d");
            this.cvs.width = artCvs.width;
            this.cvs.height = artCvs.height;
            ctx.drawImage(artCvs, 0, 0);
            this.cvsImg = this.cvs.toDataURL("image/png");
          }
        }).getCanvas();
      } catch (err) {
        console.log(err);
      }
    });
  }
  /**
   * 生成普通二维码
   * @params params 普通二维码配置参数
   */
  makeDiyBg(params) {
    QRCode.toCanvas(params.tinyUrl, {
      errorCorrectionLevel: "H",
      version: 10,
      width: params.qrconfig.qrWH,
      color: {
        dark: params.qrconfig.dark,
        light: params.qrconfig.light
      }
    })
      .then(resCvs => {
        this.qrdrawer = true;
        this.fullscreenLoading = false;
        this.$nextTick(() => {
          const ctx = this.cvs.getContext("2d");
          this.cvs.width = params.qrconfig.imgWidth;
          this.cvs.height = params.qrconfig.imgHeight;
          const img = new Image();
          img.src = params.imgUrl;
          img.onload = () => {
            const bg = ctx.createPattern(img, "no-repeat");
            ctx.fillStyle = bg;
            ctx.fillRect(
              0,
              0,
              params.qrconfig.imgWidth,
              params.qrconfig.imgHeight
            );
            if (this.userInfo.payee) {
              if (!params.qrconfig.recNameLeft) {
                params.qrconfig.recNameLeft = params.qrconfig.imgWidth / 2;
              }
              ctx.textAlign = "center";
              ctx.font = params.qrconfig.font;
              ctx.fillStyle = params.qrconfig.fontColor;
              ctx.fillText(
                "扫码向“" + this.userInfo.payee + "”付款",
                params.qrconfig.recNameLeft,
                params.qrconfig.recNameTop
              );
            }
            ctx.drawImage(
              resCvs,
              params.qrconfig.qrLeft,
              params.qrconfig.qrTop
            );
            this.cvsImg = this.cvs.toDataURL("image/png");
          };
        });
      })
      .catch(err => {
        console.log(err);
        this.$message.error(`收款码生成失败，请联系网站管理员`);
      });
  }

  /**
   * 异步获取二维码背景配置
   */
  async getQrcodeCfg() {
    return await this.axios({ baseURL: "/", url: "config.json" }).then(res => {
      return res.data;
    });
  }

  /**
   *图片转canvas
   @param file 文件信息
   */
  fileDecode(file) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onload = e => {
        const image = new Image();
        image.src = e.target.result;
        image.onload = () => {
          resolve(this.createCanvas(image));
        };
      };
    });
  }
  /**
   * 创建canvas，并扫描二维码，jsQR返回二维码数据
   * @param image 图片信息
   */
  createCanvas(image) {
    const cvs = document.createElement("canvas");
    const ctx = cvs.getContext("2d");
    cvs.width = image.width;
    cvs.height = image.height;
    ctx.drawImage(image, 0, 0, cvs.width, cvs.height);
    const imageData = ctx.getImageData(0, 0, cvs.width, cvs.height);
    return jsQR(imageData.data, imageData.width, imageData.height, {
      inversionAttempts: "dontInvert"
    });
  }
}
</script>

<style>
.swiper-container {
  padding: 20px 0 50px 0 !important;
}
.qrimg {
  width: 100%;
  height: 400px;
  border-radius: 5px !important;
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.42), 0 0 6px rgba(0, 0, 0, 0.14);
}

.el-row {
  margin-bottom: 10px;
}
.avatar-uploader {
  margin-top: 20px;
}
.avatar-uploader .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
.wx .el-upload:hover,
.wx .el-upload:focus {
  border-color: #67c23a;
}
.zfb .el-upload:hover,
.zfb .el-upload:focus {
  border-color: #409eff;
}
.qq .el-upload:hover,
.qq .el-upload:focus {
  border-color: #909399;
}
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 250px;
  line-height: 250px !important;
  text-align: center;
}
.avatar {
  width: 178px;
  height: 250px;
  display: block;
}
.el-drawer__body {
  padding: 0 20px;
  text-align: center;
}

.swiper-inner {
  width: 100%;
  height: 400px;
  padding-top: 50px;
  padding-bottom: 50px;
}
.swiper-slide {
  background-position: center;
  background-size: cover;
  width: 300px !important;
  height: 400px !important;
}
.swiper-container {
  padding: 20px 0 50px 0;
}

#cvsImg {
  width: 100%;
}
h1 {
  color: #303133;
}
.qrbox {
  text-align: center;
}
.btn {
  margin-top: 30px;
}

.el-drawer.rtl {
  min-width: 360px !important;
}
@media screen and (max-width: 1200px) {
  .el-drawer.rtl {
    width: 35% !important;
  }
}
@media screen and (max-width: 992px) {
  .el-drawer.rtl {
    width: 40% !important;
  }
}
@media screen and (max-width: 768px) {
  .qrmobile {
    flex-wrap: wrap;
  }
  .qrmobile > div {
    padding: 10px 0;
  }
  body {
    padding-bottom: 60px;
  }
  .el-drawer.rtl {
    width: 50% !important;
  }
}
@media screen and (max-width: 450px) {
  .qrmobile {
    flex-direction: column;
  }
  .qrmobile > div {
    width: 100%;
  }
  .el-drawer.rtl {
    width: 100% !important;
  }
  .el-message-box {
    width: 80% !important;
  }
}
.el-message-box__message p div {
  word-break: break-all;
  font-weight: bold;
}
</style>
